package com.saikuo.service.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.saikuo.service.api.ApiResultModel;
import com.saikuo.service.api.ErrorCode;
import com.saikuo.service.constant.ContextConfig;
import com.saikuo.service.dao.IMedicineDao;
import com.saikuo.service.service.IMedicineService;
import com.saikuo.service.utils.JSONUtil;
import com.saikuo.service.utils.StringUtil;
import com.saikuo.service.vo.MedicineDetailView;
import com.saikuo.service.vo.MedicinePicView;
import com.saikuo.service.vo.MedicineView;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Created by shanchangyu on 16/10/17.
 */
@Service
public class MedicineServiceImpl implements IMedicineService {

    @Autowired
    private IMedicineDao medicineDao;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public ApiResultModel getMedicineTopicSearchTag() {
        return new ApiResultModel(medicineDao.getMedicineTopicSearchTag());
    }

    @Override
    public ApiResultModel getMedicinesByCategoryId(int categoryId, int sortType, int page) {
        int start = page > 0 ? page - 1 : page;
        if (start == 1 || start == 2) {
            // 设置缓存KEY
            String key = getKeyParameterById("getMedicinesByCategoryId", sortType + "_" + start);
            ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
            String value = valueOperations.get(key);
            // 若缓存中存在，则直接返回
            List<MedicineView> medicineViews = jsonToBeanWithJackson(value);
            if (CollectionUtils.isNotEmpty(medicineViews)) {
                return new ApiResultModel(medicineViews);
            }
            // 若缓存中不存在，则查DB
            medicineViews = medicineDao.getMedicinesByCategoryId(categoryId, sortType, start * ContextConfig.MEDICINE_PAGE_SIZE, ContextConfig.MEDICINE_PAGE_SIZE);
            if (medicineViews != null) {
                valueOperations.set(key, JSONUtil.beanToJsonWithJackson(medicineViews),
                        ContextConfig.MIN_10, TimeUnit.MINUTES);
            }
            return new ApiResultModel(medicineViews);
        }
        return new ApiResultModel(medicineDao.getMedicinesByCategoryId(categoryId, sortType, start * ContextConfig.MEDICINE_PAGE_SIZE, ContextConfig.MEDICINE_PAGE_SIZE));
    }

    @Override
    public ApiResultModel getHotMedicines(int page) {
        int start = page > 0 ? page - 1 : page;
        if (start == 1 || start == 2) {
            // 设置缓存KEY
            String key = getKeyParameterById("getHotMedicines", +start);
            ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
            String value = valueOperations.get(key);
            // 若缓存中存在，则直接返回
            List<MedicineView> medicineViews = jsonToBeanWithJackson(value);
            if (CollectionUtils.isNotEmpty(medicineViews)) {
                return new ApiResultModel(medicineViews);
            }
            // 若缓存中不存在，则查DB
            medicineViews = medicineDao.getHotMedicines(start * ContextConfig.MEDICINE_PAGE_SIZE, ContextConfig.MEDICINE_PAGE_SIZE);
            if (medicineViews != null) {
                valueOperations.set(key, JSONUtil.beanToJsonWithJackson(medicineViews),
                        ContextConfig.MIN_10, TimeUnit.MINUTES);
            }
            return new ApiResultModel(medicineViews);
        }
        return new ApiResultModel(medicineDao.getHotMedicines(start * ContextConfig.MEDICINE_PAGE_SIZE, ContextConfig.MEDICINE_PAGE_SIZE));

    }


    @Override
    public ApiResultModel getMedicineDetailById(int medicineId) {
        MedicineDetailView medicineDetailView = medicineDao.getMedicineDetailById(medicineId);
        if (medicineDetailView == null) {
            return new ApiResultModel(ErrorCode.MEDICINE_NOT_EXIST);
        } else {
            List<MedicinePicView> medicinePicsView = medicineDao.getMedicinePicsByMedicineId(medicineId);
            medicineDetailView.setMedicinePicView(medicinePicsView);
            return new ApiResultModel(medicineDetailView);
        }
    }

    @Override
    public ApiResultModel getTopicSaleMedicines(int topicSaleId) {
        String medicineIds = medicineDao.getTopicSaleMedicine(topicSaleId);
        if (medicineIds != null && medicineIds != "") {
            List<MedicineView> medicineViews = medicineDao.getMedicinesByIds(StringUtil.stringtoList(medicineIds));
            return new ApiResultModel(medicineViews);
        }
        return new ApiResultModel();
    }

    @Override
    public ApiResultModel getMedicinesByIds(String medicineIds) {
        if (medicineIds != null && medicineIds != "") {
            List<MedicineView> medicineViews = medicineDao.getMedicinesByIds(StringUtil.stringtoList(medicineIds));
            return new ApiResultModel(medicineViews);
        }
        return new ApiResultModel();
    }

    private List<MedicineView> jsonToBeanWithJackson(String value) {
        List<MedicineView> medicineViews = new ArrayList<>();
        // 若缓存中存在，则直接返回
        if (!StringUtils.isEmpty(value)) {
            JSONArray array = JSONArray.parseArray(value);
            for (int i = 0; i < array.size(); i++) {
                String jsonObject = array.getJSONObject(i).toJSONString();
                MedicineView medicineView = JSONUtil.jsonToBeanWithJackson(jsonObject,
                        MedicineView.class);
                if (medicineView != null) {
                    medicineViews.add(medicineView);
                }
            }
        }
        return medicineViews;
    }

    protected static String getKeyParameterById(String funName, Object param) {
        return getCacheClassPrefix() + funName + "_" + param;
    }

    private static String getCacheClassPrefix() {
        return MedicineServiceImpl.class.getName() + "_";
    }
}
